/*
 * Copyright (C) 2009 Georgios J. Georgopoulos, All rights reserved.
 * 
 * This is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 3 of the License, or (at your option) any
 * later version.
 * 
 * This software is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
 * site: http://www.fsf.org.
 */
package org.gwt.mosaic.xul.client.ui;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.client.GWT;

/**
 * 
 * @author georgopoulos.georgios(at)gmail.com
 * 
 */
public abstract class Container extends Element {
  private static final long serialVersionUID = 3321547786777387749L;

  // -----------------------------------------------------------------------
  protected static final int HDLU = 2;

  // -----------------------------------------------------------------------
  protected static final int VDLU = 2;

  // -----------------------------------------------------------------------
  protected List<Element> elements = new ArrayList<Element>();

  // -----------------------------------------------------------------------
  /**
   * Default constructor.
   */
  public Container() {
    super();
  }

  // -----------------------------------------------------------------------
  /**
   * Returns the number of elements in this container.
   * 
   * @return the number or elements in this container.
   */
  public int getElementCount() {
    return elements.size();
  }

  // -----------------------------------------------------------------------
  /**
   * Gets the n<sup>th</sup> element in this container.
   * 
   * @param n the index of the element to get
   * @return the n<sup>th</sup> element in this container
   */
  public Element getElement(int n) {
    return elements.get(n);
  }

  // -----------------------------------------------------------------------
  /**
   * TODO
   * 
   * @param child
   * @return
   */
  public int indexOf(Element child) {
    return elements.indexOf(child);
  }

  // -----------------------------------------------------------------------
  /**
   * Adds the specified element to this container at the end of the element
   * list.
   * 
   * @param child the element to add to the container
   * @return the same element that was added
   */
  public Element add(Element child) {
    return add(child, -1);
  }

  // -----------------------------------------------------------------------
  /**
   * Adds the specified element to this container at the specified index in the
   * element list.
   * 
   * @param element the element to be added
   * @param index the index in the element list to insert this element, or -1 to
   *          add at the end of the list
   * @return the same element that was added
   */
  public Element add(Element element, int index) {
    if (element.parent != null) {
      element.parent.remove(element);
    }

    if (index == -1) {
      elements.add(element);
    } else {
      elements.add(index, element);
    }

    element.parent = this;

    if (GWT.isClient()) {
      elementAdded(element);
    }

    return element;
  }

  // -----------------------------------------------------------------------
  /**
   * Removes the element at the specified index from this container.
   * 
   * @param index the index of the element to remove
   * @return the element that was removed
   */
  public Element remove(int index) {
    Element element = (Element) elements.get(index);

    element.parent = null;

    elements.remove(index);

    if (GWT.isClient()) {
      elementRemoved(element);
    }

    return element;
  }

  // -----------------------------------------------------------------------
  /**
   * Removes the specified element from this container.
   * 
   * @param element the element to remove from this container
   * @return the element that was removed
   */
  public Element remove(Element element) {
    return remove(elements.indexOf(element));
  }

  // -----------------------------------------------------------------------
  /**
   * Removes all elements from this container.
   */
  public void removeAll() {
    for (Iterator<Element> iter = elements.iterator(); iter.hasNext();) {
      Element element = iter.next();

      element.parent = null;

      iter.remove();
      
      elementRemoved(element);
    }
  }

  // -----------------------------------------------------------------------
  static List<Element> searchForElementsWithUI(Container container) {
    List<Element> elementsWithUI = new ArrayList<Element>();
    for (int i = 0, n = container.getElementCount(); i < n; ++i) {
      final Element element = container.getElement(i);
      if (element.getUI() != null) {
        elementsWithUI.add(element);
      }
    }
    return elementsWithUI;
  }

  // -----------------------------------------------------------------------
  protected void elementAdded(Element e) {
    createUI();// TODO change to syncUI()
    layout();
  }

  // -----------------------------------------------------------------------
  protected void elementRemoved(Element e) {
    createUI();// TODO change to syncUI()
    layout();
  }

}
